import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import logging

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)


class ApiRequest:
    def __init__(self, base_url, timeout=10, retry_count=3):
        self.base_url = base_url.rstrip('/')  # 确保base_url末尾无斜杠
        self.session = requests.Session()
        self.timeout = timeout
        # 配置重试机制
        self._setup_retry(retry_count)
        # 默认请求头
        self.session.headers.update({
            "Content-Type": "application/json",
            "Accept": "application/json"
        })

    def _setup_retry(self, retry_count):
        """配置请求重试策略"""
        retry_strategy = Retry(
            total=retry_count,
            backoff_factor=0.5,  # 重试间隔：{backoff_factor} * (2 **({retry_count} - 1))
            status_forcelist=[429, 500, 502, 503, 504]  # 需要重试的状态码
        )
        adapter = HTTPAdapter(max_retries=retry_strategy)
        self.session.mount("http://", adapter)
        self.session.mount("https://", adapter)

    def _get_full_url(self, url):
        """处理相对路径和绝对路径"""
        if url.startswith(('http://', 'https://')):
            return url
        return f"{self.base_url}/{url.lstrip('/')}"  # 避免重复斜杠

    def send_request(self, method, url,** kwargs):
        """
        统一发送请求的方法
        :param method: 请求方法（GET/POST/PUT/DELETE等）
        :param url: 接口路径（支持相对路径和绝对路径）
        :param kwargs: 其他参数（headers/params/json/data等）
        :return: requests.Response对象
        """
        full_url = self._get_full_url(url)
        method = method.upper()
        logger.info(f"发送请求: {method} {full_url}")
        logger.debug(f"请求参数: {kwargs}")

        try:
            # 支持所有HTTP方法
            response = self.session.request(
                method=method,
                url=full_url,
                timeout=self.timeout,
                **kwargs
            )
            logger.info(f"响应状态码: {response.status_code}")
            logger.debug(f"响应内容: {response.text}")
            response.raise_for_status()  # 抛出HTTP错误状态码异常
            return response
        except requests.RequestException as e:
            logger.error(f"请求失败: {str(e)}", exc_info=True)
            raise  # 重新抛出异常供用例捕获

